package web.service;

import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;

import com.jfinal.kit.StrKit;

import web.model.AdminUser;
import web.model.Permissions;
import web.model.Roles;
import web.model.temp.SimpleUser;

/**  
 * @ClassName: ShiroDbRealm  
 * @Description: 基于db实现的shiro realm 
 * @author 李飞 (lifei@wellbole.com)   
 * @date 2014年9月8日 下午10:10:38
 * @since V1.0.0  
 */
public class ShiroDbRealm extends AuthorizingRealm {
    
	private static AdminService service = new AdminService();
    public ShiroDbRealm(){
		setAuthenticationTokenClass(UsernamePasswordToken.class);
    }

    /**
     * 认证回调函数,登录时调用.
     */    
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token){
		UsernamePasswordToken authcToken = (UsernamePasswordToken) token;
        String accountName = authcToken.getUsername();
        if (StrKit.isBlank(accountName)) {
            throw new AuthenticationException("用户名不可以为空");
        }
		AdminUser user = service.getUserByName(accountName);
        if (null == user) {
			throw new IncorrectCredentialsException("用户名或者密码错误");
        }
		if (user.getIsActive()) {
            throw new LockedAccountException("该用户已被锁定");
        }
		return new SimpleAuthenticationInfo(new SimpleUser(user.getId(), user.getUsername()),
				user.getPassword(), getName());
    }

    /**
     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //User user = (User) principals.fromRealm(getName()).iterator().next();
    	SimpleUser simpleUser = (SimpleUser) principals.fromRealm(getName()).iterator().next();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if( null == simpleUser){
        	return info;
        }
		AdminUser user = AdminUser.dao.findById(simpleUser.getId());
        if( null == user){
        	return info;
        }
		List<Roles> roles = user.getRoles();
		if (roles != null && !roles.isEmpty()) {
			for (Roles role : roles) {
                //角色的名称及时角色的值
				info.addRole(role.getName());
                addResourceOfRole(role,info);
            }
        }
		// 增加用户权限关联
		List<Permissions> perms = service.getPermission(simpleUser.getId());
		if (perms != null) {
			for (Permissions permissions : perms) {
				info.addStringPermission(permissions.getPermission());
			}
		}
        return info;
    }
    
	private void addResourceOfRole(Roles role, SimpleAuthorizationInfo info) {
		List<Permissions> resources = role.getPermissions();
		if (resources != null && !resources.isEmpty()) {
			for (Permissions resource : resources) {
                //资源代码就是权限值，类似user：list
				info.addStringPermission(resource.getPermission());
            }
        }
    }

	public void clearCached() {
		PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
		clearCache(principals);
	}

	@Override
	public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
		super.clearCachedAuthorizationInfo(principals);
	}

	@Override
	public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
		super.clearCachedAuthenticationInfo(principals);
	}

	@Override
	public void clearCache(PrincipalCollection principals) {
		Cache cache = getAuthorizationCache();
		super.clearCache(principals);
	}
    /**
     * 更新用户授权信息缓存.
     */
    public void clearCachedAuthorizationInfo(String principal) {
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
        clearCachedAuthorizationInfo(principals);
    }

    /**
     * 清除所有用户授权信息缓存.
     */
    public void clearAllCachedAuthorizationInfo() {
        Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
        if (cache != null) {
            for (Object key : cache.keys()) {
                cache.remove(key);
            }
        }
    }
}
